#include "jsonrpcmessage.h"


#include <QVariant>
#include <QJsonArray>


int JsonRpcMessage::v_uniqueIdentifier = 1;


JsonRpcMessage::JsonRpcMessage(const JsonRpcMessage &message) : v_object(message.v_object) {
    v_type = message.v_type;
}

JsonRpcMessage::JsonRpcMessage(const QJsonObject &obj)
{
    v_object = obj;
    if(v_object.contains("error")){
        v_type = Error;
    }else{
        if(v_object.contains("id")){
            if(v_object.contains("result")){
                v_type = JsonRpcMessage::Result;
            }else{
                if(v_object.value("id") == QJsonValue()){
                    v_type = JsonRpcMessage::Notification;
                }else{
                    v_type = JsonRpcMessage::Request;
                }
            }
        }else{
            v_type = JsonRpcMessage::Notification;
        }
    }
}


JsonRpcMessage& JsonRpcMessage::operator=(const JsonRpcMessage& message){
    v_object = message.v_object;
    v_type = message.v_type;
    return *this;
}


JsonRpcMessage::Type JsonRpcMessage::type() const{
    return v_type;
}

int JsonRpcMessage::id() const{
    if(!v_object.contains("id"))
        return -1;

    return v_object.value("id").toVariant().toInt();
}

QString JsonRpcMessage::method() const{
    return v_object.value("method").toVariant().toString();
}

QVariantList JsonRpcMessage::params() const{
    return v_object.value("params").toArray().toVariantList();
}



QVariant JsonRpcMessage::result() const{
    if(!v_object.contains("result"))
        return QVariant();
    return v_object.value("result").toVariant();
}


bool JsonRpcMessage::error() const{
    return v_type == Error;
}


int JsonRpcMessage::errorCode() const{
    if(!v_object.contains("error"))
        return 0;

    return v_object.value("error").toObject().value("code").toVariant().toInt();
}


QString JsonRpcMessage::errorMessage() const{
    if(!v_object.contains("error"))
        return QString();
    return v_object.value("error").toObject().value("message").toVariant().toString();
}


QVariant JsonRpcMessage::errorData() const{
    if(!v_object.contains("error"))
        return QVariant();
    return v_object.value("error").toObject().value("data").toVariant();
}



//STATIC
JsonRpcMessage JsonRpcMessage::createRequest(const QString& methodName, const QVariantList& paramList){
    QJsonObject obj;
    obj.insert("jsonrpc", QLatin1String("2.0"));
    obj.insert("method", methodName);
    obj.insert("id", QJsonValue(v_uniqueIdentifier++));
    if(!paramList.isEmpty()){
        obj.insert("params", QJsonArray::fromVariantList(paramList));
    }

    JsonRpcMessage message(obj);
    message.v_type = Request;
    return message;
}


// STATIC
JsonRpcMessage JsonRpcMessage::createNotification(const QString& methodName, const QVariantList& paramList){
    QJsonObject obj;
    obj.insert("jsonrpc", QLatin1String("2.0"));
    obj.insert("method", methodName);
    obj.insert("id", QJsonValue());
    if(!paramList.isEmpty()){
        obj.insert("params", QJsonArray::fromVariantList(paramList));
    }

    JsonRpcMessage message(obj);
    message.v_type = Notification;
    return message;
}


JsonRpcMessage JsonRpcMessage::createResponse(const QVariant& result) const{
    QJsonObject obj;
    obj.insert("jsonrpc", QLatin1String("2.0"));
    obj.insert("result", QJsonValue::fromVariant(result));
    obj.insert("id", QJsonValue(this->id()));

    JsonRpcMessage message(obj);
    message.v_type = Result;
    return message;
}


JsonRpcMessage JsonRpcMessage::createError(int code, const QString& message, const QVariant& data) const{
    QJsonObject errorObj;
    errorObj.insert("code", code);
    errorObj.insert("message", message);
    errorObj.insert("data", QJsonValue::fromVariant(data));

    QJsonObject obj;
    obj.insert("jsonrpc", QLatin1String("2.0"));
    obj.insert("error", QJsonValue(errorObj));
    obj.insert("id", QJsonValue(this->id()));
    JsonRpcMessage mess(obj);
    mess.v_type = Error;

    return mess;
}
